package fr.bludwarf.skywarrior.joueur;

import fr.bludwarf.skywarrior.evenements.Cycle;
import fr.bludwarf.skywarrior.exceptions.EtherInsuffisantException;
import fr.bludwarf.skywarrior.exceptions.MateriauxInsuffisantsException;
import fr.bludwarf.skywarrior.exceptions.RessourcesInsuffisantesException;

/**
 * Quantité de matériaux, d'éther et de nourriture
 * @since 2 nov. 2011
 */
public class Ressources
{
	
	public static final Ressources VIDES = new Ressources(0, 0, 0);

	/** Production de matériaux */
	int _mat;
	
	/** Production d'éther */
	int _eth;
	
	/** Production de nourriture */
	int _nourriture;
	
	/**
	 * @param mat production de matériaux
	 * @param eth production d'éther
	 * @param nourriture production de nourriture
	 */
	public Ressources(final int mat, final int eth, final int nourriture) {
		_mat = mat;
		_eth = eth;
		_nourriture = nourriture;
	}

	public static Ressources total(final int nb, final Ressources production)
	{
		return new Ressources(production._mat * nb, production._eth * nb, production._nourriture * nb);
	}

	/**
	 * Cumul de deux productions.
	 * @param production autre production à ajouter à la production courante
	 * @param cumulNourriture la nourriture doit être cumulée ?
	 */
	public void add(Ressources production, final boolean cumulNourriture) {
		_mat += production._mat;
		_eth += production._eth;
		if (cumulNourriture)
		{
			_nourriture += production._nourriture;
		}
	}

	/**
	 * Enlève une certaine quantité de matériaux, d'éther et de population (ici la nourriture est considérée comme pop donc cumul = false)
	 * @param cout autre production à enlever à la production courante
	 * @throws RessourcesInsuffisantesException si pas assez de ressources
	 */
	public void remove(Ressources cout) throws RessourcesInsuffisantesException {
		
		if (cout._mat > _mat)
		{
			throw new MateriauxInsuffisantsException(cout._mat);
		}
		if (cout._eth > _eth)
		{
			throw new EtherInsuffisantException(cout._eth);
		}
		
		_mat -= cout._mat;
		_eth -= cout._eth;
	}
	
	/**
	 * @return la production de matériaux
	 */
	public int materiaux()
	{
		return _mat;
	}
	
	/**
	 * @return la production d'éther
	 */
	public int ether()
	{
		return _eth;
	}
	
	/**
	 * @return la production de nourriture
	 */
	public int nourriture()
	{
		return _nourriture;
	}

	public void nourriture(int nourriture) {
		_nourriture = nourriture;
	}
	
	@Override
	protected Object clone() {
		return new Ressources(this._mat, this._eth, this._nourriture);
	}

	public void materiaux(int materiaux) {
		_mat = materiaux;
	}

	public void ether(int ether) {
		_eth = ether;
	}

	public boolean couvre(Ressources res)
	{
		return this.materiaux() >= res.materiaux() && this.ether() >= res.ether() && this.nourriture() >= res.nourriture();
	}

	public boolean couvrira(Ressources cout)
	{
		return !(materiaux() == 0 && cout.materiaux() != 0 || ether() == 0 && cout.ether() != 0 || nourriture() == 0 && cout.nourriture() != 0);
	}

	/**
	 * Arrondis supérieurs
	 * @param dureeReelle
	 * @return
	 */
	public Ressources parCycle(double dureeReelle)
	{
		double cycles = dureeReelle / Cycle.DUREE;
		return new Ressources(
			(int) Math.ceil((double) materiaux() / cycles),
			(int) Math.ceil((double) ether() / cycles),
			(int) Math.ceil((double) nourriture() / cycles)
		);
	}
	
	@Override
	public String toString()
	{
		return String.format("m=%+05d e=%+05d n=%+03d", materiaux(), ether(), nourriture());
	}
}
